版本控制的定义
版本控制的定义
版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。
VCS版本控制的定义
VCS版本控制系统的定义
rcs 本地版本控制系统
它的工作原理是在硬盘上保存补丁集(补丁是指文件修订前后的变化);通过应用所有的补丁,可以重新计算出各个版本的文件内容。
rcs 本地版本控制系统原理
集中化版本控制系统de 诞生
都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。
分布式版本控制系统DVCS 原理
客户端并不只提取最新版本的文件快照,而是把代码仓库完整地镜像下来。
这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。
因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份。
CVCS集中化版本控制系统de 诞生
,许多这类系统都可以指定和若干不同的远端代码仓库进行交互。
git 诞生
速度 简单的设计 对非线性开发模式的强力支持(允许成千上万个并行开发的分支) 完全分布式 有能力高效管理类似 Linux 内核一样的超大规模项目(速度和数据量)
对待数据的方法
这类系统(CVS、Subversion、Perforce、Bazaar 等等)将它们保存的信息看作是一组基本文件和每个文件随时间逐步累积的差异。
git 处理数据的方式: 快照流,制作快照流,并保存快照流索引
你提交更新,或在 Git 中保存项目状态时,它主要对当时的全部文件制作一个快照并保存这个快照的索引。
git 处理数据的方式: 快照流,制作快照流,并保存快照流索引,
和其他vcs 相比git更像是一个小型的文件系统
计算校验和的机制叫哈西
Git 中所有数据在存储前都计算校验和,然后以校验和来引用。
计算校验和的机制叫
计算校验和的机制叫sha-1序列
哈希是由文件内容和目录结构
计算校验和的机制叫sha-1序列
哈希是由git 系统中文件的内容或目录结构计算出的
计算校验和的机制叫sha-1序列
哈希是由git 系统中文件的内容或目录结构计算出的
git 数据库保存的信息,是以文件内容的哈希值
计算校验和的机制叫sha-1序列
哈希是由git 系统中文件的内容或目录结构计算出的
git 数据库保存的信息,是以文件内容的哈希值来索引,而不是文件名
三种状态,已tijiao ,已修改,已暂存 引入git 项目的三个工作区域的概念:git 仓库,工作目录, 暂存区域
已提交(committed)、已修改(modified)和已暂存(staged)。
已提交表示数据已经安全的保存在本地数据库中。
已修改表示修改了文件,但还没保存到数据库中。
已暂存表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。
工作区域:git仓库,工作目录,暂存区
暂存区域是一个文件,保存了下次将提交的文件列表信息,一般在 Git 仓库目录中。
已提交状态。
已暂存状态。
就是已修改状态。
Git 自带一个 git config 的工具来帮助设置控制 Git 外观和行为的配置变量。
每一个级别覆盖上一级别的配置,所以 .git/config 的配置变量会覆盖 /etc/gitconfig 中的配置变量。
可以使用 git config --list 命令来列出所有 Git 当时能找到的配置。
有两种取得 Git 项目仓库的方法。
第一种是在现有项目或目录下导入所有文件到 Git 中; 第二种是从一个服务器克隆一个现有的 Git 仓库。
Git 区别于其它版本控制系统的一个重要特性,Git 克隆的是该 Git 仓库服务器上的几乎所有数据,而不是仅仅复制完成你的工作所需要文件
Git 支持多种数据传输协议
工作目录下的每一个文件都不外乎这两种状态:已跟踪或未跟踪
已跟踪文件的三种状态
状态可能处于未修改,已修改或已放入暂存区。
commit 提交的信息是处于暂存区状态
提交所有暂存了的修改,
commit 提交的信息是处于暂存区状态,提交之后,文件进入git 仓库中, 此时工作目录的文件状态变成未修改状态
commit 提交(创建快照)的信息是处于暂存区状态,提交之后,文件进入git 仓库中, 此时工作目录的文件状态变成未修改状态
git add多功能命令
多功能命令:可以用它开始跟踪新文件,或者把已跟踪的文件放到暂存区,还能用于合并时把有冲突的文件标记为已解决状态等。
commit 命令只提交git add 之后文件版本
现在提交,CONTRIBUTING.md 的版本是你最后一次运行 git add 命令时的那个版本,而不是你运行 git commit 时,在工作目录中的当前版本
commit 命令只提交git add 之后文件版本
实测.git commit . 会将工作目录下已修改(add 之前),已暂存(add 之后),两种状态一并提交
glob 模式是指 shell 所使用的简化了的正则表达式。
星号(*)匹配零个或多个任意字符;[abc] 匹配任何一个列在
git diff 本身只显示尚未暂存的改动,而不是自上次提交以来所做的所有改动。
运行 git diff 看暂存前后的变化:
用 git diff --cached 查看已经暂存起来的变化:(--staged 和 --cached 是同义词)
commit 命令只提交git add 之后文件版本
实测.git commit . 会将工作目录下已修改(add 之前),已暂存(add 之后),两种状态一并提交
git commit -a 跳过暂存区
git rm 命令完成此项工作,并连带从工作目录中删除指定的文件,这样以后就不会出现在未跟踪文件清单中了。
git commit --amend 这个命令会将暂存区中的文件提交。
git reset HEAD
不加选项地调用 git reset 并不危险 — 它只会修改暂存区域。
git checkout -- [file] 是一个危险的命令,这很重要。
你对那个文件做的任何修改都会消失 - 你只是拷贝了另一个文件来覆盖它。
除非你确实清楚不想要那个文件了,否则不要使用这个命令。
那些被删除的分支中的提交或使用 --amend 选项覆盖的提交也可以恢复(阅读 “数据恢复” 了解数据恢复)。
然而,任何你未提交的东西丢失后很可能再也找不到了。
管理远程仓库包括了解如何添加远程仓库、移除无效的远程仓库、管理不同的远程分支并定义它们是否被跟踪等等。
运行 git remote 命令。
它会列出你指定的每一个远程服务器的简写。
运行 git remote add
拉取 Paul 的仓库中有但你没有的信息,可以运行 git fetch pb:
git fetch [remote-name] 这个命令会访问远程仓库,从中拉取所有你还没有的数据。
执行完成后,你将会拥有那个远程仓库中所有分支的引用,可以随时合并或查看。
git pull 通常会从最初克隆的服务器上抓取数据并自动尝试合并到当前所在的分支。
git fetch 命令会将数据拉取到你的本地仓库 - 它并不会自动合并或修改你当前的工作。
当准备好时你必须手动将其合并入你的工作。
git push [remote-name] [branch-name]。
当
git push origin master 只有当你有所克隆服务器的写入权限,并且之前没有人推送过时,这条命令才能生效。
使用 git remote show [remote-name] 命令。
git add 命令使用文件或目录的路径作为参数;如果参数是目录的路径
git diff --cached 命令。(
也可以在 commit 命令后添加 -m 选项,将提交信息与命令放在同一行,
git commit 加上 -a 选项,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git add 步骤:
你想让文件保留在磁盘,但是并不想让 Git 继续跟踪。
当你忘记添加 .gitignore 文件,不小心把一个很大的日志文件或一堆 .a 这样的编译生成文件添加到暂存区时,这一做法尤其有用。
为达到这一目的,使用 --cached 选项:
移动文件git mv file newfile
以改名方式达到移动操作
如果在 Git 中重命名了某个文件,仓库中存储的元数据并不会体现出这是一次改名操作。
commit
git branch 命令仅仅 创建 一个新分支,并不会自动切换到新分支中去。
一是使 HEAD 指回 master 分支,二是将工作目录恢复成 master 分支所指向的快照内容。
git log --oneline --decorate --graph --all ,它会输出你的提交历史、各个分支的指向以及项目的分支分叉情况。
Git 的分支实质上仅是包含所指对象校验和(长度为 40 的 SHA-1 值字符串)的文件,所以它的创建和销毁都异常高效。
,由于每次提交都会记录父对象,所以寻找恰当的合并基础(译注:即共同祖先)也是同样的简单和高效。
这些高效的特性使得 Git 鼓励开发人员频繁地创建和使用分支。
,当你试图合并两个分支时,如果顺着一个分支走下去能够到达另一个分支,那么 Git 在合并两者的时候,只会简单的将指针向前推进(指针右移),因为这种情况下的合并操作没有需要解决的分歧 — — 这就叫做 “快进(fast-forward)”。
做了一个新的快照并且自动创建一个新的提交指向它。
解决了所有文件里的冲突之后,对每个文件使用 git add 命令来将其标记为冲突已解决。
后期打标签
你可能想要执行外部命令,而不是一个 Git 子命令。
如果是那样的话,可以在命令前面加入 ! 符号。
,在你切换分支之前,保持好一个干净的状态。
有一些方法可以绕过这个问题(即,保存进度(stashing) 和 修补提交(commit amending)),我们会在 “储藏与清理” 中看到关于这两个命令的介绍。
git checkout -b [branchname] [tagname] 在特定的标签上创建一个新分支:
检出到你想合并入的分支,然后运行 git merge 命令:
确保这些已完成的特性分支(短期分支,比如之前的 iss53 分支)能够通过所有测试,并且不会引入更多 bug 之后,就可以合并入主干分支中,等待下一次的发布。
Git 中,每个开发者同时扮演着节点和集线器的角色
Git 允许多个远程仓库存在,使得这样一种工作流成为可能:每个开发者拥有自己仓库的写权限和其他所有人仓库的读权限。
GitHub 和 GitLab 等集线器式(hub-based)工具最常用的工作流程。人们可以容易地将某个项目派生成为自己的公开仓库,向这个仓库推送自己的修改,并为每个人所见。
这么做最主要的优点之一是你可以持续地工作,而主仓库的维护者可以随时拉取你的修改。
贡献者不必等待维护者处理完提交的更新 — — 每一方都可以按照自己节奏工作。
“重写历史” 描述了重写历史与交互式暂存文件的若干有用的 Git 技巧 - 在将工作发送给其他人前使用这些工具来帮助生成一个干净又易懂的历史。
Subversion 会对编辑的不同文件在服务器上自动进行一次合并,但 Git 要求你在本地合并提交。
John 必须抓取 Jessica 的改动并合并它们,才能被允许推送。
使用 rebase 命令将提交到某一分支上的所有修改都移至另一分支上,就好像“重新播放”一样。
无论是通过变基,还是通过三方合并,整合的最终结果所指向的快照始终是一样的,只不过提交历史不同罢了。
变
无论是通过变基,还是通过三方合并,整合的最终结果所指向的快照始终是一样的,只不过提交历史不同罢了。
变基是将一系列提交按照原有次序依次应用到另一分支上,而合并是把最终结果合在一起。
变基操作的实质是丢弃一些现有的提交,然后相应地新建一些内容一样但实际上不同的提交。
实际上,Git 除了对整个提交计算 SHA-1 校验和以外,也对本次提交所引入的修改计算了校验和 — — 即 “patch-id”。
如果你拉取被覆盖过的更新并将你手头的工作基于此进行变基的话,一般情况下 Git 都能成功分辨出哪些是你的修改,并把它们应用到新分支上。
Git 没有一个改变历史工具,但是可以使用变基工具来变基一系列提交,基于它们原来的 HEAD 而不是将其移动到另一个新的上面。
Git 没有一个改变历史工具,但是可以使用变基工具来变基一系列提交,基于它们原来的 HEAD 而不是将其移动到另一个新的上面。
通过交互式变基工具,可以在任何想要修改的提交后停止,然后修改信息、添加文件或做任何想做的事情。
记住这是一个变基命令 - 在 HEAD~3..HEAD 范围内的每一个提交都会被重写,无论你是否修改信息。
交互式变基给你一个它将会运行的脚本。
它将会从你在命令行中指定的提交(HEAD~3)开始,从上到下的依次重演每一个提交引入的修改。
通过交互式变基工具,也可以将一连串提交压缩成一个单独的提交
使一个子目录做为新的根目录 假设已经从另一个源代码控制系统中导入,并且有几个没意义的子目录(trunk、tags 等等)。
HEAD~(HEAD 的父结点)
一个分离历史记录到两个单独的仓库的示例中实践了此命令,同时使用了 --onto 选项。
一个分离历史记录到两个单独的仓库的示例中实践了此命令,同时使用了 --onto 选项。
你就能使用 reset 来轻松快速地将它们压缩成单个提交,也
引用日志只存在于本地仓库,
同样是指向第一父提交,因此 HEAD~ 和 HEAD^ 是等价的。
而区别在于你在后面加数字的时候。
HEAD~2 代表 “第一父提交的第一父提交”,也就是 “祖父提交” — — Git 会根据你指定的次数获取对应的第一父提交。
例如,在之前的列出的提交历史中,HEAD~3 就是
它允许你让 Git 记住解决一个块冲突的方法,这样在下一次看到相同冲突时,Git 可以为你自动地解决它。
使用 git add --patch 来部分暂存文件
更详细的解释,包括做改动的动机和它的实现与之前行为的对比 - 这是一个值得遵循的好规则。